#if NETFX
using System;
using System.Collections.Generic;
using NUnit.Framework;
using ServiceStack.Text;

namespace ServiceStack.Redis.Tests.Exploits;

public class MSVR76883 : RedisClientTestsBase
{
    class StorageObject
    {
        public string name { get; set; }

        public Dictionary<string, object> stuff { get; set; }
    }

    //this payload loads 
    const string payloadString = @"{""stuff"":{""nested"":
        {""__type"":""System.Configuration.Install.AssemblyInstaller, System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"",
        ""Path"":""c:\\temp\\RunCalcOnLoad.dll""
        }}}";
    
    [Explicit("Try to force an RCE from dynamically creating an instance of AssemblyInstaller")] 
    public void Try_to_RunCalcOnLoad()
    {
        var typeName = @"System.Configuration.Install.AssemblyInstaller, System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
        var path = @"c:\\temp\\RunCalcOnLoad.dll";
        
        var type = Type.GetType(typeName);
        var installer = type.CreateInstance();
        installer.GetType().ToString().Print();
        var pathAccessor = TypeProperties.Get(type).GetAccessor("Path");
        pathAccessor.PublicSetter(installer, path);
        pathAccessor.PublicGetter(installer).ToString().Print();

        // var installer = new System.Configuration.Install.AssemblyInstaller();
        // installer.Path = path;

        //readline so program does not exit before RCE executes
        //System.Console.ReadLine();
    }
    
    [Test]
    public void Does_not_allow_deserialization_of_non_whitelist_type()
    {
        Assert.Throws<NotSupportedException>(() => payloadString.FromJson<StorageObject>());
        
        var manager = new RedisManagerPool("localhost:6379");
        
        using var client = manager.GetClient();

        //write malicious data as string
        client["hack"] = payloadString;

        //read malicious data as object
        Assert.Throws<NotSupportedException>(() => client.Get<StorageObject>("hack"));
    }
}
#endif